#include <MathVector.hpp>
using namespace Mathing;

#ifndef _CLASSMODELINGPLANEEQUATION_
#define _CLASSMODELINGPLANEEQUATION_

namespace Mathing {

template <class vertexType = Vector3f>
class PlaneEquation : Mathing::MathVector<float, 4>
{
public:
    ~PlaneEquation() {}
    PlaneEquation(float A=0 , float B=0, float C=0, float D=0) : Mathing::MathVector<float, 4>(A, B, C, D) {}
    PlaneEquation(vertexType& P1, vertexType& P2, vertexType& P3);
    
    float getA() {return this->vec[0];}
    void setA(float A) {this->vec[0] = A;}
    
    float getB() {return this->vec[1];}
    void setB(float B) {this->vec[1] = B;}
    
    float getC() {return this->vec[2];}
    void setC(float C) {this->vec[2] = C;}
    
    float getD() {this->vec[3];}
    void setD(float D) {this->vec[3] = D;}
    
    float evaluatePoint(vertexType& point);
};

template <class vertexType>
PlaneEquation<vertexType>::PlaneEquation(vertexType& P1, vertexType& P2, vertexType& P3)
{
    this->vec[0] = P1[1]*(P2[2]-P3[2] ) + P2[1]*(P3[2]-P1[2]) + P3[1]*(P1[2]-P2[2]);
	this->vec[1] = P1[2]*(P2[0]-P3[0]) + P2[2]*(P3[0]-P1[0]) + P3[2]*(P1[0]-P2[0]);
	this->vec[2] = P1[0]*(P2[1]-P3[1]) + P2[0]*(P3[1]-P1[1]) + P3[0]*(P1[1]-P2[1]);
	this->vec[3] = -(P1[0]*( P2[1]*P3[2] - P3[1]*P2[2] )
	               + P2[0]*( P3[1]*P1[2] - P1[1]*P3[2] )
	               + P3[0]*( P1[1]*P2[2] - P2[1]*P1[2] ) );
}

template <class vertexType>
float PlaneEquation<vertexType>::evaluatePoint(vertexType& point)
{
    return this->vec[0] * point[0] +
           this->vec[1] * point[1] +
           this->vec[2] * point[2] +
           this->vec[3];
}

}//namespace Modeling

#endif
